using System.ComponentModel.DataAnnotations;
using Coderoom.ScrumPlanner.Domain;
using Coderoom.ScrumPlanner.Domain.Validation;
using Coderoom.ScrumPlanner.Tests.Unit.Internal;
using Xunit;

namespace Coderoom.ScrumPlanner.Tests.Unit.ContainerTests
{
	public class EntityTests
	{
		[Fact]
		public void TitleProperty_is_marked_required()
		{
			// arrange
			var attributes = AttributeTestHelper.GetCustomPropertyAttributes<Entity,RequiredAttribute>("Title");

			// assert
			Assert.NotNull(attributes);
			Assert.Equal(1, attributes.Length);
			Assert.Equal("Please enter a title.", attributes[0].ErrorMessageResourceType.GetString(attributes[0].ErrorMessageResourceName));
		}

		[Fact]
		public void Validation_passes_when_container_is_proper()
		{
			// arrange
			var container = new EntityProxy();
			container.Title = "title";
			container.Slug = "slug";

			// act
			var result = EntityValidator.Validate(container);

			// assert
			Assert.IsType<ValidationResult>(result);
			Assert.True(result.IsValid);
			Assert.Equal(0, result.Errors.Count);
		}

		[Fact]
		public void Validation_fails_when_Title_is_null()
		{
			// arrange
			var container = new EntityProxy();
			container.Title = null;
			container.Slug = "slug";

			// act
			var result = EntityValidator.Validate(container);

			// assert
			Assert.IsType<ValidationResult>(result);
			Assert.False(result.IsValid);
			Assert.Equal(1, result.Errors.Count);
			Assert.Equal("Title", result.Errors[0].PropertyName);
			Assert.Equal("Please enter a title.", result.Errors[0].Message);
			Assert.Equal(container, result.Errors[0].ValidationTarget);
		}

		[Fact]
		public void Validation_fails_when_Title_is_empty()
		{
			// arrange
			var container = new EntityProxy();
			container.Title = "";
			container.Slug = "slug";

			// act
			var result = EntityValidator.Validate(container);

			// assert
			Assert.IsType<ValidationResult>(result);
			Assert.False(result.IsValid);
			Assert.Equal(1, result.Errors.Count);
			Assert.Equal("Title", result.Errors[0].PropertyName);
			Assert.Equal("Please enter a title.", result.Errors[0].Message);
			Assert.Equal(container, result.Errors[0].ValidationTarget);
		}

		[Fact]
		public void Validation_fails_when_Slug_is_null()
		{
			// arrange
			var container = new EntityProxy();
			container.Title = "title";
			container.Slug = null;

			// act
			var result = EntityValidator.Validate(container);

			// assert
			Assert.IsType<ValidationResult>(result);
			Assert.False(result.IsValid);
			Assert.Equal(1, result.Errors.Count);
			Assert.Equal("Slug", result.Errors[0].PropertyName);
			Assert.Equal("Please enter a slug.", result.Errors[0].Message);
			Assert.Equal(container, result.Errors[0].ValidationTarget);
		}

		[Fact]
		public void Validation_fails_when_Slug_is_empty()
		{
			// arrange
			var container = new EntityProxy();
			container.Title = "title";
			container.Slug = "";

			// act
			var result = EntityValidator.Validate(container);

			// assert
			Assert.IsType<ValidationResult>(result);
			Assert.False(result.IsValid);
			Assert.Equal(1, result.Errors.Count);
			Assert.Equal("Slug", result.Errors[0].PropertyName);
			Assert.Equal("Please enter a slug.", result.Errors[0].Message);
			Assert.Equal(container, result.Errors[0].ValidationTarget);
		}

		[Fact]
		public void CreateSlug_converts_space_to_hyphen()
		{
			// act
			var slug = Entity.CreateSlug("text text");

			// assert
			Assert.Equal("text-text", slug);
		}

		[Fact]
		public void CreateSlug_converts_period_to_hyphen()
		{
			// act
			var slug = Entity.CreateSlug("text.text");

			// assert
			Assert.Equal("text-text", slug);
		}

		[Fact]
		public void CreateSlug_converts_uppercase_text_lo_lowercase_text()
		{
			// act
			var slug = Entity.CreateSlug("lower UPPER Capital MiXeD");

			// assert
			Assert.Equal("lower-upper-capital-mixed", slug);
		}

		private class EntityProxy : Entity { }
	}
}